<?php

declare(strict_types=1);

namespace App\Job;

use _PHPStan_adbc35a1c\Nette\Neon\Exception;
use App\Model\Applet;
use App\Model\AppletPlayletRel;
use App\Model\Playlet;
use App\Model\PlayletEpisodes;
use App\Model\PlayletTag;
use GuzzleHttp\Client;
use Hyperf\AsyncQueue\Job;
use Psr\Log\LoggerInterface;
use Hyperf\Utils\ApplicationContext;
use Hyperf\Logger\LoggerFactory;
use function PHPUnit\Framework\exactly;

class DyDramaJob extends Job
{

    public $playet_id;

    public $applet_id;
    protected LoggerInterface $logger;


    //获取token
    public static $getTokenUrl = "https://open.douyin.com/oauth/client_token/";

    //上传图片接口，上传对应的剧目封面图
    public static $uploadImageUrl = "https://open.douyin.com/api/playlet/v2/resource/upload/";
    //授权小程序
    public static $authorizeUrl = "https://open.douyin.com/api/playlet/v2/auth/authorize/";

    //创建短剧
    public static $dramaCreateUrl = "https://open.douyin.com/api/playlet/v2/video/create/";
    //编辑短剧
    public static $dramaUpdateUrl = "https://open.douyin.com/api/playlet/v2/video/edit/";

    //剧目送审
    public static $dramaReviewUrl = "https://open.douyin.com/api/playlet/v2/video/review/";
    //剧目绑定
    public static $dramaBindUrl = "https://open.douyin.com/api/playlet/v2/album/bind/";
    public function __construct(int $playet_id,int $applet_id)
    {
        $container = ApplicationContext::getContainer();
        $this->logger = $container->get(LoggerFactory::class)->get('log', 'dyvod');
        $this->playet_id = $playet_id;
        $this->applet_id = $applet_id;
    }

    public function handle()
    {
        try {
            $this->logger->info('开始上传提审剧目');
            $this->logger->info('查询短剧是否存在',[$this->playet_id]);
//            return;
            //获取短剧ID
            $playletData = Playlet::query()->where(['id' => $this->playet_id])->first();

            if(!empty($playletData)){

                $this->logger->info('查询小程序是否存在',[$this->applet_id]);
                $appletData = Applet::query()->where(['id' => $this->applet_id])->first();
                if(!empty($appletData)) {
                    $applet_name = $appletData->name;
                    $playlet_name = $playletData->name;
                    $tag_list = PlayletTag::query()->where(['playlet_id' => $this->playet_id])->limit(3)->pluck('tag_id');
                    //如果为空，则标签未其他
                    if($tag_list->isEmpty()){
                        $tag_list = [46];
                    }else{
                        $tag_list = $tag_list->toArray();
                    }
                    //获取token
                    $accessToken = $this->getDyAccessToken($appletData->id,$appletData->app_id,$appletData->app_secret);

                    if(!empty($accessToken)){

                        $episodes_count = PlayletEpisodes::query()->where(['playlet_id' => $this->playet_id])->count();
                        //统计短剧剧集总数
                        $episode_list = PlayletEpisodes::query()->where(['playlet_id' => $this->playet_id,'is_dy_upload' => 3])
                            ->where('dy_cloud_id','!=',0)
                            ->where('open_video_id','!=',0)
                            ->orderBy('playlet_number','asc')
                            ->select(['id','dy_cloud_id','playlet_number','open_video_id','playlet_number_name'])->get();
                        $media_count = count($episode_list);
                        if($episodes_count == $media_count && $media_count != 0){

                            $open_pic_id = 0;
                            $playlet_introduction = $playletData->introduction;
                            $registration_number = $playletData->registration_number;
                            $open_pic_id = $this->dramaImageUpload($accessToken,$playletData->cover,$appletData->app_id);
                            //数据库有主从延迟，返回的open_pic_id，不能马上使用，需要等1s左右。
                            sleep(3);
                            if(!empty($playletData->album_id)){
                                $album_id = $playletData->album_id;
                            }else{
                                $this->logger->info('小程序：'.$applet_name.' 短剧：'.$playlet_name.'调用图片素材接口，上传封面图');
                                $this->logger->info('小程序：' . $applet_name . ' 短剧：' . $playlet_name . '开始上传剧目');
                                //创建短剧
                               $album_id = $this->dramaCreate($accessToken,
                                    $playlet_name, //剧目名称
                                    $playlet_introduction,//简介
                                    $media_count, //集数
                                    $open_pic_id, //图片ID
                                    $tag_list, //标签
                                    $registration_number, //备案号
                                    $appletData->app_id, //appID
                                );
                               if(!empty($album_id)){
                                   $playletData->album_id = $album_id;
                                   $playletData->album_status = 1;
                                   $playletData->save();
                               }
                            }
                            //数据库有主从延迟，返回的album_id，不能马上使用，需要等1s左右。
                            sleep(3);
                            //短剧编辑，短剧与视频绑定
                            if(!empty($album_id)){
                                $episode_info_list = array();

                                foreach ($episode_list as $item){

                                    $episode_info_list[] =[
                                        'title' => $item->playlet_number_name,
                                        'seq'   => $item->playlet_number,
                                        'cover_list' => [$open_pic_id],
                                        'open_video_id' => $item->open_video_id
                                    ];
                                }
                                $episodeData = $this->dramaUpdate($accessToken,
                                    $album_id, //抖音剧目ID
                                    $episode_info_list, //剧集信息
                                    $appletData->app_id, //appID
                                );
                                if(!empty($episodeData)){
                                    //2024-01-12 旧流程 先授权再绑定页面，新流程，先绑定页面再授权
                                    //查询所有小程序授权
                                    $appletInfo =Applet::query()->where(['type' => 2])->pluck('app_id')->toArray();
                                    //绑定抖音集数ID
                                    $episode_id_map = $episodeData['episode_id_map'];
                                    $version =  $episodeData['version'];

                                    foreach ($episode_list as $item){
                                        $playlet_number = $item->playlet_number;
                                        if(!empty($episode_id_map[$playlet_number])){
                                            $item->dy_album_id = $album_id;
                                            $item->dy_media_status = 1;
                                            $item->dy_episodes_id = $episode_id_map[$playlet_number];
                                            $item->save();
                                            //绑定页面
                                            $this->dramaBind($accessToken,$album_id,$episode_id_map[$playlet_number],$playletData->id,$playlet_number,$appletInfo);
                                        }
                                    }
                                    //授权小程序
                                    $this->authorize($album_id,$accessToken,$appletData->app_id,$appletInfo);
                                    //短剧送审
                                    $reviewRes = $this->dramaReview($accessToken,$album_id,$appletData->app_id);
                                    if(!empty($reviewRes)){
                                        $playletData->album_version = $version;
                                        $playletData->save();
                                    }else{
                                        $playletData->album_status = 4;
                                        $playletData->save();
                                    }
                                }else{
                                    $this->logger->error('小程序：'.$applet_name.' 短剧：'.$playlet_name.'编辑抖音短剧失败，短剧和剧集绑定失败');
                                }

                            }else{
                                $this->logger->error('小程序：'.$applet_name.' 短剧：'.$playlet_name.'创建抖音短剧失败');
                            }
                        }else{
                            $this->logger->error('小程序：'.$applet_name.' 短剧：'.$playlet_name.'拥有的剧集和上传成功的剧集不一致');
                        }
                    }else{
                        $this->logger->error('小程序:'.$applet_name.' 短剧:'.$playlet_name.' 没有对应的token');
                    }

                }else{
                    $this->logger->error('小程序不存在',[$this->applet_id]);
                }
            }else{
                $this->logger->error('短剧不存在',[$this->playet_id]);
            }
        }catch (\Exception $e){
            $playletData->drama_status = 5;
            $playletData->drama_msg = $e->getMessage();
            $playletData->save();
            $this->logger->error('请求抖音提交审核剧目接口|错误：' . $e->getLine() . '|' . $e->getMessage());
        }
    }

    public function authorize($album_id,$accessToken,$app_id,$appletInfo){

        //查询所有小程序授权
//        $appletInfo =Applet::query()->where(['type' => 2])->pluck('app_id')->toArray();
        $params         = [
            "ma_app_id"   =>$app_id,
            "album_id"   => $album_id,
            "app_id_list"   => $appletInfo,
        ];
        $taskUrl = self::$authorizeUrl;
        $this->logger->info('请求剧目授权信息数据：'.PHP_EOL.var_export(['result' => $params], true));
        $this->logger->info('请求剧目授权信息Url：'.$taskUrl);
        $postResult  = $this->request($params, $taskUrl,'POST',$accessToken);
        if($postResult['err_no'] == 0){
            $this->logger->info('调用剧目授权信息接口成功 返回数据：'.PHP_EOL.var_export(['result' => $postResult], true));
            return $postResult;
        }else{
            $this->logger->error('调用剧目授权信息接口失败 返回数据：'.PHP_EOL.var_export(['result' => $postResult], true));
        }
        return false;
    }


    public function dramaImageUpload($accessToken,$cover_url,$app_id){
        $params = [
            'resource_type' => 2,
            'ma_app_id' =>  $app_id,
            'image_meta' =>[
                'url' =>$cover_url,
            ]
        ];
        $uploadUrl = self::$uploadImageUrl;
        $this->logger->info('请求数据：'.PHP_EOL.var_export(['result' => $params], true));
        $this->logger->info('请求Url：'.$uploadUrl);
        //开始上传
        $uploadResult  = $this->request($params, $uploadUrl,'POST',$accessToken);
        if($uploadResult['err_no'] == 0){
            $this->logger->info('上传图片成功 返回数据：'.PHP_EOL.var_export(['result' => $uploadResult], true));
            $open_pic_id = $uploadResult['data']['image_result']['open_pic_id'];
            return $open_pic_id;
        }else{
            $this->logger->error('上传图片失败 返回数据：'.PHP_EOL.var_export(['result' => $uploadResult], true));
        }
        return false;
    }

    public function dramaCreate($accessToken,$playlet_name,$playlet_introduction,$seq_num,$open_pic_id,$tag_list,$registration_number,$app_id){
        $params = [
            'ma_app_id' =>  $app_id,
            'album_info' =>[
                'title' => $playlet_name,
                'seq_num' => $seq_num,
                'cover_list' =>[$open_pic_id],
                'year' => date('Y'),
                'album_status' => 3,
                'recommendation' => $playlet_name,
                'desp' =>$playlet_introduction,
                'qualification' => 2,
                'record_info' =>[
                    'ordinary_record_num' => $registration_number
                ],
                'tag_list' => $tag_list,
            ]
        ];
        $createUrl = self::$dramaCreateUrl;
        $this->logger->info('请求数据：'.PHP_EOL.var_export(['result' => $params], true));
        $this->logger->info('请求Url：'.$createUrl);
        //开始上传
        $createResult  = $this->request($params, $createUrl,'POST',$accessToken);
        if($createResult['err_no'] == 0){
            $this->logger->info('创建短剧成功 返回数据：'.PHP_EOL.var_export(['result' => $createResult], true));
            $album_id = $createResult['data']['album_id'];
            return $album_id;
        }else{
            $this->logger->error('创建短剧失败 返回数据：'.PHP_EOL.var_export(['result' => $createResult], true));
        }
        return false;
    }

    public function dydramaUpdate($accessToken,$album_id,$episode_info_list,$app_id){

        $params = [
            'ma_app_id' =>  $app_id,
            'album_id'=>$album_id,
            'episode_info_list' =>$episode_info_list
        ];
        $updateUrl = self::$dramaUpdateUrl;
//        $this->logger->info('请求数据：'.PHP_EOL.var_export(['result' => $params], true));
        $this->logger->info('请求Url：'.$updateUrl);
        //开始上传
        $updateResult  = $this->request($params, $updateUrl,'POST',$accessToken);
        if($updateResult['err_no'] == 0){
            $this->logger->info('编辑短剧成功 返回数据：'.PHP_EOL.var_export(['result' => $updateResult], true));
            return $updateResult['data'];
        }else{
            $this->logger->error('编辑短剧失败 返回数据：'.PHP_EOL.var_export(['result' => $updateResult], true));
        }
        return false;
    }



    public function dramaUpdate($accessToken,$album_id,$episode_info_list,$app_id){
        //一次只能上传100
        $returnData = [];
        if(count($episode_info_list) > 100){
            $divisionList  = [];
            $count = count($episode_info_list);
            foreach ($episode_info_list as $key => $item){
                $divisionList[] = $item;
                if(count($divisionList) == 100){
                     $updateData = $this->dydramaUpdate($accessToken,$album_id,$divisionList,$app_id);
                     $divisionList = [];
                     $returnData = $updateData;
                     sleep(10);
                }
                if($key+1 == $count){
                    $updateData = $this->dydramaUpdate($accessToken,$album_id,$divisionList,$app_id);
                    $returnData = $updateData;
                }



            }
        }else{
            $returnData = $this->dydramaUpdate($accessToken,$album_id,$episode_info_list,$app_id);
        }
        return $returnData;
    }
    public function dramaBind($accessToken,$album_id,$episode_id,$playlet_id,$playlet_epoisode_id,$appletInfo){
        try {
            sleep(1);

            foreach ($appletInfo as $applet){


                $params = [
                    'schema_bind_type' => 1,
                    'app_id' => $applet,
                    "single_schema_bind" => [
                        'album_id'=>$album_id,
                        "episode_id" => $episode_id,
                        "path" => "pages/videopage/videopage",
                        "params" => [
                            ["key" => "pid", "value" => (string)$playlet_id],
                            ["key" => "peid", "value" => (string)$playlet_epoisode_id],
                            ["key" => "dt", "value" => (string)time()] //无用的参数
                        ]
                    ]
                ];
                $updateUrl = self::$dramaBindUrl;
                $this->logger->info('请求小程序：',[$applet]);
//                $this->logger->info('请求数据：'.PHP_EOL.var_export(['result' => $params], true));
                $this->logger->info('请求Url：'.$updateUrl);
                //开始上传
                $reviewResult  = $this->request($params, $updateUrl,'POST',$accessToken);
                if($reviewResult['err_no'] == 0){
                    $this->logger->info('短剧绑定页面成功 短剧episode_id：',[$episode_id]);
//                    return $reviewResult;
                }else{
                    $this->logger->error('短剧绑定页面失败 返回数据：'.PHP_EOL.var_export(['result' => $reviewResult], true));
                }
            }
            return true;

        }catch (\Exception $e){
            $this->logger->error('请求抖音|错误：' . $e->getLine() . '|' . $e->getMessage());
            return $this->dramaBind($accessToken,$album_id,$episode_id,$playlet_id,$playlet_epoisode_id,$appletInfo);
        }
    }
    public function dramaReview($accessToken,$album_id,$app_id){
        $params = [
            'ma_app_id' =>  $app_id,
            'album_id'=>$album_id,
        ];
        $updateUrl = self::$dramaReviewUrl;
        $this->logger->info('请求数据：'.PHP_EOL.var_export(['result' => $params], true));
        $this->logger->info('请求Url：'.$updateUrl);
        //开始上传
        $reviewResult  = $this->request($params, $updateUrl,'POST',$accessToken);
        if($reviewResult['err_no'] == 0){
            $this->logger->info('短剧送审成功 返回数据：'.PHP_EOL.var_export(['result' => $reviewResult], true));
            return $reviewResult;
        }else{
            $this->logger->error('短剧送审失败 返回数据：'.PHP_EOL.var_export(['result' => $reviewResult], true));
        }
        return false;
    }


    public function getDyAccessToken($applet_id,$app_id,$app_secret){

        $container = ApplicationContext::getContainer();

        $redis = $container->get(\Hyperf\Redis\RedisFactory::class)->get('dy');

        $key = 'dy_admin_access_token';
        $key .= $applet_id;
        $accessToken = $redis->get($key);
        if(empty($accessToken)){
            $params         = [
                'grant_type' => 'client_credential',
                'client_key'    => $app_id,
                'client_secret'   => $app_secret
            ];
            //获取token
            $accessTokenInfo     = $this->request($params, self::$getTokenUrl,'POST');
            if (!empty($accessTokenInfo['data']['access_token'])){
                $accessToken = $accessTokenInfo['data']['access_token'];
                $redis->setex($key,7100,$accessToken);
            }else{
                $accessToken = "";
            }
        }
        return $accessToken;
    }

    /**
     * 传入数组进行HTTP POST请求
     */
    function request(array $params, string $url,string $method,string $access_token = null)
    {
        $client   = new Client([
            'timeout' => 3
        ]);
        $headers       = ['Content-Type' => 'application/json'];
        if(!empty($access_token)){
            $headers['access-token'] = $access_token;
        }

        $requestParams = [
            'headers' => $headers,
        ];
        if ($method == 'GET') {
            $requestParams['query'] = $params;
        } else {
            $requestParams['json'] = $params;//json_encode($params,JSON_UNESCAPED_UNICODE);
        }
        $response = $client->request($method,$url, $requestParams);
        if ($response->getStatusCode() !== 200) {
            return '';
        }
        $result   = $response->getBody()->getContents();
        $resultArr = json_decode($result,true);
        return $resultArr;

    }
}